package com.xiangxiao.rpan.utils;


import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.City;
import com.maxmind.geoip2.record.Country;
import com.maxmind.geoip2.record.Subdivision;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;

/**
 * @auther xiangxiao
 * @email 573768011@qq.com
 * @data 2023/4/13 11:13
 */
@Slf4j
public class GeoIpUtil {
  public static final String UN_KNOW = "unKnown";

  private GeoIpUtil() {
  }

  /**
   * 获取指定ip的地理位置，中文格式
   *
   * @param ip
   * @return
   */
  public static String getGeoOfIp(String ip) {
    return getGeoOfIp(ip, Locale.CHINESE);
  }

  /**
   * 获取指定ip的地理位置，根据locate来指定格式
   *
   * @param ip
   * @param locale 支持的格式：de,ru,pt-BR,ja,en,fr,zh-CN,es
   * @return
   */
  public static String getGeoOfIp(String ip, Locale locale) {
    String[] geoArrOfIp = getGeoArrOfIp(ip, locale);
    return null == geoArrOfIp ? null : geoArrOfIp[0] + geoArrOfIp[1] + geoArrOfIp[2];
  }

  /**
   * 获取ip的地理位置信息,中文形式
   *
   * @param ip
   * @return
   */
  public static String[] getGeoArrOfIp(String ip) {
    return getGeoArrOfIp(ip, Locale.CHINESE);
  }

  public static String[] getGeoArrOfIp(String ip, Locale locale) {
    try {
      ClassPathResource resource = new ClassPathResource("GeoLite2-City.mmdb");
      String locateStr = locale.getLocale();
      // 创建 DatabaseReader对象
      DatabaseReader reader = new DatabaseReader.Builder(resource.getInputStream()).build();
      InetAddress ipAddress = InetAddress.getByName(ip);
      CityResponse response;
      try {
        response = reader.city(ipAddress);
      } catch (Exception e) {
        return null;
      }
      Country country = response.getCountry();
      String countryName = country.getNames().get(locateStr);
      Subdivision subdivision = response.getMostSpecificSubdivision();
      String provinceName;
      if (subdivision.getNames().containsKey(locateStr)) {
        provinceName = subdivision.getNames().get(locateStr);
      } else {
        provinceName = subdivision.getNames().get(Locale.ENGLISH.getLocale());
      }
      City city = response.getCity();
      String cityName;
      if (city.getNames().containsKey(locateStr)) {
        cityName = city.getNames().get(locateStr);
      } else {
        cityName = city.getNames().get(Locale.ENGLISH.getLocale());
      }

      if (null == provinceName) {
        provinceName = "";
      }

      if (null == cityName) {
        cityName = "";
      }
      return new String[]{countryName, provinceName, cityName};
    } catch (Exception e) {
      return null;
    }
  }

  public enum Locale {
    /**
     * 德语
     */
    GERMAN("de"),
    /**
     * 俄语
     */
    RUSSIAN("ru"),
    /**
     * 葡萄牙/巴西语
     */
    PORTUGUESE_BRAZIL("pt-BR"),
    /**
     * 日语
     */
    JAPAN("ja"),
    /**
     * 英语
     */
    ENGLISH("en"),
    /**
     * 法语
     */
    FRENCH("fr"),
    /**
     * 中文
     */
    CHINESE("zh-CN"),
    /**
     * 西班牙语
     */
    SPANISH("es");

    /**
     * 缩写
     */
    private String localeContent;

    Locale(String localeContent) {
      this.localeContent = localeContent;
    }

    public String getLocale() {
      return localeContent;
    }
  }

  /**
   * 获取Ip地址
   *
   * @param request
   * @return
   */
  public static String getIpAddress(HttpServletRequest request) {

    String Xip = request.getHeader("X-Real-IP");
    String XFor = request.getHeader("X-Forwarded-For");
    if (StringUtils.isNotEmpty(XFor) && !UN_KNOW.equalsIgnoreCase(XFor)) {
      //多次反向代理后会有多个ip值，第一个ip才是真实ip
      int index = XFor.indexOf(",");
      if (index != -1) {
        return XFor.substring(0, index);
      } else {
        return XFor;
      }
    }
    XFor = Xip;
    if (StringUtils.isNotEmpty(XFor) && !UN_KNOW.equalsIgnoreCase(XFor)) {
      return XFor;
    }
    if (StringUtils.isBlank(XFor) || UN_KNOW.equalsIgnoreCase(XFor)) {
      XFor = request.getHeader("Proxy-Client-IP");
    }
    if (StringUtils.isBlank(XFor) || UN_KNOW.equalsIgnoreCase(XFor)) {
      XFor = request.getHeader("WL-Proxy-Client-IP");
    }
    if (StringUtils.isBlank(XFor) || UN_KNOW.equalsIgnoreCase(XFor)) {
      XFor = request.getHeader("HTTP_CLIENT_IP");
    }
    if (StringUtils.isBlank(XFor) || UN_KNOW.equalsIgnoreCase(XFor)) {
      XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (StringUtils.isBlank(XFor) || UN_KNOW.equalsIgnoreCase(XFor)) {
      XFor = request.getRemoteAddr();
    }
    log.info(" ip : [{}]", XFor);
    return XFor;
  }
}
